#include "config.h"
#include <iostream>
//#include <iostream>
namespace sylar {


ConfigVarBase::ptr Config::LookUpBase(const std::string& name)
{
    RWMutexType::ReadLock lock(Config::GetMuetx());
    auto it = GetDatas().find(name);
    return it == GetDatas().end() ? nullptr : it->second;
}


// 转换
// "A.B", 10
// A:
//  B: 10
//  C: str
static void YamlToListAllMember(const std::string& prefix
                    , const YAML::Node& node
                    , std::list<std::pair<std::string, const YAML::Node>>& output)
{
    if (prefix.find_first_not_of("abcdefghikjlmnopqrstuvwxyz._012345678") 
                != std::string::npos)
    {
        SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "Config Invald name " << prefix;
        return ;
    }

    output.push_back(std::make_pair(prefix, node));
   // std::cout << "node.IsMap() : " << node.IsMap() << "\n";
    if (node.IsMap())
    {
        for (auto it = node.begin();
            it != node.end(); ++it)
            {   
                // std::cout << "map \n"; 
                // if (it->second.IsSequence())
                // {
                //     for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1)
                //     {
                //         std::cout << "seq " << *it1 << "\n";
                //     }
                // }
                YamlToListAllMember( prefix.empty() ? it->first.Scalar() : prefix + "." + it->first.Scalar(), it->second, output);
            }
    }

}


void Config::LoadFromYaml(const YAML::Node& root)
{
    std::list<std::pair<std::string, const YAML::Node>> all_node;

    // 将yaml格式转成list 
    YamlToListAllMember("", root, all_node);

    for (auto& i : all_node)
    {

        std::string key = i.first;
        //std::cout << "cout"  << key << "\n";
        if (key.empty())
        {
            continue;
        }

        std::transform(key.begin(), key.end(), key.begin(), ::tolower);
        // 查询约定
        ConfigVarBase::ptr val = LookUpBase(key);

        if (val)
        {
            if (i.second.IsScalar())
            {
                val->fromString(i.second.Scalar());
            }
            else 
            {
                std::stringstream ss;
                ss << i.second;
                val->fromString(ss.str());
            }
        }

    }

}

void Config::Visit(std::function<void(ConfigVarBase::ptr)> cb)
{
    RWMutexType::ReadLock lock(Config::GetMuetx());
    ConfigVarMap& m = Config::GetDatas();

    for (auto i : m)
    {
        cb(i.second);
    }

}

}